﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Security;
using IGolovkine.Core.Linq;

namespace IGolovkine.ShoutCastRipper
{
    public class FileCommand : IFileCommand
    {
        private readonly string _fileName;
        private readonly string _arguments;
        private readonly string _workingDirectory;
        private readonly string _userName;
        private readonly string _password;
        private readonly string _domain;

        public FileCommand(string fileName, string arguments, string workingDirectory, string userName, string password, string domain)
        {
            _fileName = fileName;
            _arguments = arguments;
            _workingDirectory = workingDirectory;
            _userName = userName;
            _password = password;
            _domain = domain;
        }

        public void Execute(IDictionary<string, object> context)
        {
            string fileName = this.InsertContext(_fileName, context);
            string arguments = null;
            if (!string.IsNullOrEmpty(_arguments))
            {
                arguments = this.InsertContext(_arguments, context);
            }

            try
            {
                Process process = new Process();
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.FileName = fileName;
                if (arguments.IndexOf(" ") != -1)
                {
                    arguments = EncloseInDoubleCommans(arguments);
                }
                process.StartInfo.Arguments = arguments;

                if (!string.IsNullOrEmpty(_workingDirectory))
                {
                    process.StartInfo.WorkingDirectory = _workingDirectory;
                }

                if (!string.IsNullOrEmpty(_userName))
                {
                    process.StartInfo.UserName = _userName;
                }

                if (!string.IsNullOrEmpty(_password))
                {
                    process.StartInfo.Password = this.CreateSecureString(_password);
                }

                if (!string.IsNullOrEmpty(_domain))
                {
                    process.StartInfo.Domain = _domain;
                }

                process.Start();
            }
            catch (Exception ex)
            {
                string message = string.Format("Error executing '{0} {1}': {2}", fileName, arguments, ex.Message);
                throw new FileCommandExecutionException(message, ex);
            }
        }

        private static string EncloseInDoubleCommans(string value)
        {
            return "\"" + value + "\"";
        }

        private SecureString CreateSecureString(string value)
        {
            SecureString result = new SecureString();
            value.ToCharArray().ForEach(c => result.AppendChar(c));
            result.MakeReadOnly();
            return result;
        }

        private string InsertContext(string value, IDictionary<string, object> context)
        {
            string temp = value;
            int index = 0;
            foreach (var pair in context)
            {
                temp = temp.Replace(pair.Key, index.ToString());
                index++;
            }
            temp = string.Format(temp, context.Values.ToArray());
            return temp;
        }
    }
}
